package redis.event;

import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.listener.ChannelTopic;
import org.springframework.data.redis.listener.RedisMessageListenerContainer;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;
import redis.clients.jedis.JedisPoolConfig;
import redis.event.listener.KeyExpireListener;

import java.util.List;
import java.util.concurrent.Executor;
import java.util.concurrent.ThreadPoolExecutor;

@Configuration
@EnableConfigurationProperties(RedisListenerProperties.class)
public class RedisEventConfiguration {

    @Value("${spring.redis.host}")
    private String host;
    @Value("${spring.redis.port}")
    private Integer port;
    @Value("${spring.redis.password}")
    private String password;

    @Bean
    @ConditionalOnClass(KeyExpireListener.class)
    public KeyExpireEventListener keyExpireEventListener() {
        System.out.println("=======================注入RedisEventConfiguration-->keyExpireEventListener");
        return new KeyExpireEventListener();
    }

    @Bean
    @ConditionalOnClass({KeyExpireEventListener.class, KeyExpireListener.class})
    public Executor keyExpireExecutor(RedisListenerProperties redisListenerProperties) {
        System.out.println("=======================注入RedisEventConfiguration-->keyExpireExecutor");
        ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
        System.out.println("=======================redisListenerProperties.getCorePoolSize():"+redisListenerProperties.getCorePoolSize());
        executor.setCorePoolSize(redisListenerProperties.getCorePoolSize());
        executor.setMaxPoolSize(redisListenerProperties.getMaxPoolSize());
        executor.setQueueCapacity(redisListenerProperties.getQueueCapacity());
        executor.setKeepAliveSeconds(redisListenerProperties.getKeepAliveSeconds());
        executor.setThreadNamePrefix(redisListenerProperties.getThreadNamePrefix());
        executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
        executor.initialize();
        return executor;
    }

    @SuppressWarnings("SpringJavaAutowiringInspection")
    @Bean
    @ConditionalOnClass({ KeyExpireEventListener.class, RedisConnectionFactory.class})
    public RedisMessageListenerContainer redisMessageListenerContainer(
            @Qualifier("keyExpireExecutor") Executor keyExpireExecutor,
            KeyExpireEventListener keyExpireEventListener,
            RedisConnectionFactory redisConnectionFactory){

        //Jedis失效监听中拷贝过来的，等于配置了redis的Ex,这里的参数不应该硬编码，考虑从配置文件中读取
        JedisPool pool = new JedisPool(new JedisPoolConfig(), host,port);
        Jedis jedis = pool.getResource();
        jedis.auth(password);//不加启动会报错-------redis可以设置密码，不影响失效监听
        String parameter = "notify-keyspace-events";
        List<String> notify = jedis.configGet(parameter);
        if(notify.get(1).equals("")){
            jedis.configSet(parameter, "Ex"); //过期事件
        }

        System.out.println("=======================注入RedisEventConfiguration-->redisMessageListenerContainer");
        RedisMessageListenerContainer container = new RedisMessageListenerContainer();
        container.setConnectionFactory(redisConnectionFactory);
        container.setTaskExecutor(keyExpireExecutor);
        ChannelTopic topic = new ChannelTopic("__keyevent@0__:expired");                        //代表监听redis数据库0的失效事件
        container.addMessageListener(keyExpireEventListener, topic);
        return container;

    }

}
